package com.frame.core.mybatis;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Signature;

import java.sql.Connection;

/**
 * MySql数据库分页插件
 */
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}))
public class MySqlPagingInterceptor extends AbstractPagingInterceptor {

    @Override
    public String getSelectTotalSql(String originalSql) {
        String sql = originalSql.toLowerCase();

        //原始Sql转换为小写,利用小写Sql计算关键字位置
        StringBuilder sqlBuilder = new StringBuilder(sql);
        //原始Sql
        StringBuilder orgSqlBuilder = new StringBuilder(originalSql);

        int orderByPos = 0;
        if ((orderByPos = sqlBuilder.lastIndexOf(ORDER_BY)) != -1) {
            sqlBuilder.delete(orderByPos, sqlBuilder.length());
            orgSqlBuilder.delete(orderByPos, orgSqlBuilder.length());
        }

        if ((orderByPos = sqlBuilder.lastIndexOf(GROUP_BY)) != -1) {
            orgSqlBuilder.insert(0, "select count(1) from ( ");
            orgSqlBuilder.append(" ) as _alias");
            return orgSqlBuilder.toString();
        }

        if (sqlBuilder.indexOf(UNION) != -1) {
            orgSqlBuilder.insert(0, "select count(1) as my_count from ( ").append(" ) as _alias");
            return orgSqlBuilder.toString();
        }

        if (selectAppearCount(sqlBuilder) > 1) {
            orgSqlBuilder.insert(0, "select count(1) as my_count from ( ").append(" ) as _alias");
            return orgSqlBuilder.toString();
        }

        int fromPos = sqlBuilder.lastIndexOf(FROM);
        if (fromPos != -1) {
            orgSqlBuilder.delete(0, fromPos);
            orgSqlBuilder.insert(0, "select count(1) as my_count ");
        }

        return orgSqlBuilder.toString();
    }

    @Override
    public String getSelectPagingSql(String originalSql, PageBounds bounds) {
        StringBuilder sqlBuilder = new StringBuilder(originalSql);
        sqlBuilder.append(" limit " + bounds.getmOffset() + "," + bounds.getPageSize());
        String sql = sqlBuilder.toString();

        return sql;
    }

    private static int selectAppearCount(StringBuilder orgSql) {
        StringBuilder sql = new StringBuilder(orgSql);
        int appear = 0;
        int selectPos = -1;
        while ((selectPos = sql.indexOf(SELECT)) != -1) {
            sql.delete(0, selectPos + SELECT.length());
            appear++;
        }
        return appear;
    }

}
